// --------------------------------------------------------------------------------------------------------------------
// <copyright file="RetentionProcessor.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace ExecutionTool.Retention
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;

    using ExecutionTool.Common;
    using ExecutionTool.CopyOnPremises;
    using ExecutionTool.ImportExport;
    using ExecutionTool.Profile;

    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using Microsoft.Practices.ServiceLocation;

    public class RetentionProcessor
    {
        #region Fields

        private readonly LogWriter logger;

        private readonly IOnPremisesAdapter onPremisesAdapter;

        private readonly Profile profile;

        private readonly IStorageAdapter storageAdapter;

        #endregion

        #region Constructors and Destructors

        public RetentionProcessor(Profile profile, IStorageAdapter storageAdapter, IOnPremisesAdapter onPremisesAdapter, LogWriter logger = null)
        {
            Helper.CheckForNull(profile, "profile");
            Helper.CheckForNull(storageAdapter, "storageAdapter");
            Helper.CheckForNull(onPremisesAdapter, "onPremisesAdapter");

            this.profile = profile;
            this.storageAdapter = storageAdapter;
            this.onPremisesAdapter = onPremisesAdapter;
            this.logger = logger ?? ServiceLocator.Current.GetInstance<LogWriter>();
        }

        #endregion

        #region Public Methods and Operators

        public RetentionProcessResult Process()
        {
            var result = new RetentionProcessResult();

            var daysToKeep = this.profile.Orchestration.DaysToKeep;
            if (daysToKeep <= 0)
            {
                return result;
            }

            var tasks = new List<Task>();

            if (this.profile.Orchestration.Export)
            {
                var taskBlob = Task.Factory.StartNew(
                    () =>
                        {
                            var blobList = this.storageAdapter.ListBlobs(this.profile.TargetAzureStorage, this.profile.Name.ToLower());

                            foreach (var blob in
                                blobList.Where(blob => DateTime.UtcNow - blob.Properties.LastModifiedUtc > TimeSpan.FromDays(daysToKeep)))
                            {
                                blob.DeleteIfExists();
                                this.logger.LogInformation(string.Format("During retention processing, blob [{0}] was deleted.", blob.Uri));
                                result.DeletedBlobs.Add(blob.Name, blob.Properties.LastModifiedUtc);
                            }
                        });
                tasks.Add(taskBlob);
            }

            if (this.profile.Orchestration.CopyToOnPremises)
            {
                var taskOnPremises = Task.Factory.StartNew(
                    () =>
                        {
                            var blobList =
                                this.onPremisesAdapter.ListBlobs(
                                    Path.Combine(this.profile.TargetOnPremisesLocation.Location, this.profile.Name.ToLower()));

                            foreach (var blob in
                                blobList.Where(blob => DateTime.UtcNow - blob.CreationTimeUtc > TimeSpan.FromDays(daysToKeep)))
                            {
                                File.Delete(blob.FullName);
                                this.logger.LogInformation(string.Format("During retention processing, blob [{0}] was deleted.", blob.FullName));
                                result.DeletedOnPremisesBlobs.Add(blob.FullName, blob.CreationTimeUtc);
                            }
                        });
                tasks.Add(taskOnPremises);
            }

            if (tasks.Count > 0)
            {
                Task.WaitAll(tasks.ToArray());
            }

            return result;
        }

        #endregion
    }
}
